/*
 * RntlHandler.java
 *
 * Created on April 11, 2007, 10:01 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package edu.byu.isys413.group1E.handlers;

import edu.byu.isys413.group1E.data.ConceptualBO;
import edu.byu.isys413.group1E.data.ConceptualDAO;
import edu.byu.isys413.group1E.data.ConceptualRentalBO;
import edu.byu.isys413.group1E.data.ConceptualRentalDAO;
import edu.byu.isys413.group1E.data.EmployeeBO;
import edu.byu.isys413.group1E.data.FeeBO;
import edu.byu.isys413.group1E.data.FeeDAO;
import edu.byu.isys413.group1E.data.ForRentBO;
import edu.byu.isys413.group1E.data.ForRentDAO;
import edu.byu.isys413.group1E.data.ForSaleBO;
import edu.byu.isys413.group1E.data.ForSaleDAO;
import edu.byu.isys413.group1E.data.ProductBO;
import edu.byu.isys413.group1E.data.ProductDAO;
import edu.byu.isys413.group1E.data.RentalBO;
import edu.byu.isys413.group1E.data.RentalDAO;
import edu.byu.isys413.group1E.data.RevenueSourceBO;
import edu.byu.isys413.group1E.data.SaleBO;
import edu.byu.isys413.group1E.data.StoreBO;
import edu.byu.isys413.group1E.data.StoreProductBO;
import edu.byu.isys413.group1E.data.StoreProductDAO;
import edu.byu.isys413.group1E.handlers.MyDate;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import edu.byu.isys413.group1E.data.*;
import edu.byu.isys413.group1E.handlers.*;
import java.text.NumberFormat;

/**This class handles all business logic concerning Rentals
 *
 * @author KC Kern
 */
public class RntlHandler {
    private static RntlHandler instance = null;
    /** Creates a new instance of RntlHandler */
    public RntlHandler() {
    }
    /**
     * 
     * @return 
     */
    public static synchronized RntlHandler getInstance() {
        if (instance == null) {
            instance = new RntlHandler();
        }
        return instance;
    }
    /**
     * Returns an ArrayList<String> of all of the Rental Categories (Assuming that an item is available for rent)
     */
    public ArrayList<String> getRentalCategoriesList(){
        ArrayList<String> categoryList = new ArrayList<String>();
        try {
            //retrieve the products
            ArrayList<ProductBO> prodList = (ArrayList<ProductBO>)ConceptualRentalDAO.getInstance().readAll();
            
            //convert them to conceptualRentalBO objects
            ArrayList<ConceptualRentalBO> crList = new ArrayList<ConceptualRentalBO>();
            for(int x=0;x<crList.size();x++){
                crList.add((ConceptualRentalBO)prodList.get(x));
            }
            categoryList.add("All Categories");
            for (int i = 0; i < crList.size(); i++) {
                String temp = crList.get(i).getCategory();
                if (!categoryList.contains(temp)) {
                    categoryList.add(temp);
                }
                System.out.println(categoryList.get(i));
            }
        } catch (ConnectionPoolException ex) {
            ex.printStackTrace();
        } catch (SQLException ex) {
            ex.printStackTrace();
        } catch (DataException ex) {
            ex.printStackTrace();
        }
        return categoryList;
    }
    /**
     * 
     * @return 
     */
    public String[] getRentalCategoriesArray(){
        ArrayList<String> categoryList = new ArrayList<String>();
        String[] rcArray = null;// = new String[crList.size()];
        try {
            //retrieve the products
            ArrayList<ProductBO> prodList = (ArrayList<ProductBO>)ConceptualRentalDAO.getInstance().readAllCRs();
            
            //convert them to conceptualRentalBO objects
            ArrayList<ConceptualRentalBO> crList = new ArrayList<ConceptualRentalBO>();
            
            for(int x=0;x<prodList.size();x++){
                crList.add((ConceptualRentalBO)prodList.get(x));
            }
            
            categoryList.add("All Categories");
            for (int i = 0; i < crList.size(); i++) {
                String temp = crList.get(i).getCategory();
                if (!categoryList.contains(temp)) {
                    categoryList.add(temp);
                }
//                System.out.println(categoryList.get(i));
            }
            
            //String[] rcArray = new String[crList.size()];
            //now parse them for the needed information
            rcArray = new String[categoryList.size()];
            for (int i = 0; i < categoryList.size(); i++) {
                rcArray[i] = categoryList.get(i);
            }
            
        } catch (ConnectionPoolException ex) {
            ex.printStackTrace();
        } catch (SQLException ex) {
            ex.printStackTrace();
        } catch (DataException ex) {
            ex.printStackTrace();
        }
        return rcArray;
    }
    /**
     *creates a transaction with a blank sale
     *
     * @throws java.lang.Exception
     * @return
     */
    public RevenueSourceBO processNewRental(ArrayList<String> input)throws Exception{
        RentalBO rb = (RentalBO)RentalDAO.getInstance().create();
        rb.setDateOut(input.get(0));
        rb.setDateDue(input.get(1));
        rb.setPricePerDay(Double.parseDouble(input.get(2)));
        rb.setType("rental");
        rb.setPrice(this.calcPrice(rb.getDateOut(), rb.getDateDue(), rb.getPricePerDay()));
        rb.setDescription(input.get(8));
        RevenueSourceBO revSrcBO = (RevenueSourceBO)rb;
        return revSrcBO;
    }//end addRentalToTXLine
    /**
     *
     * @param saleBO
     * @param session
     * @throws edu.byu.isys413.group1E.DataException
     * @throws edu.byu.isys413.group1E.ConnectionPoolException
     * @throws edu.byu.isys413.group1E.SalesException
     */
    public void postRentalReservation(SaleBO saleBO, Session session) throws DataException, ConnectionPoolException, SalesException{
        ConceptualDAO conceptualDAO = ConceptualDAO.getInstance();
        ConceptualBO conceptualBO = null;
        ForSaleDAO forSaleDAO = ForSaleDAO.getInstance();
        ForSaleBO forSaleBO = null;
        StoreBO storeBO = session.getStore();
        EmployeeBO employeeBO = session.getEmployee();
        StoreProductDAO storeProductDAO = StoreProductDAO.getInstance();
        StoreProductBO storeProductBO = null;
        
        if(saleBO.getReturnLine()==true){
            
            if(saleBO.getProduct().getProdType().equals("physical")){
                forSaleBO = (ForSaleBO)saleBO.getProduct();
                if(forSaleBO.getNewUsed()==false){
                    throw new SalesException("You can't return a used Item.");
                }//end catch for returning a used item
                forSaleBO.setSold(false);
                storeProductBO = storeProductDAO.read(storeBO.getStoreID(), forSaleBO.getConceptual().getProductID());
                storeProductBO.setQtyOnHand(storeProductBO.getQtyOnHand()+saleBO.getQuantity());
                
                storeProductDAO.save(storeProductBO);
                forSaleDAO.save(forSaleBO);
            }//end posting of physical sale
            if(saleBO.getProduct().getProdType().equals("conceptual")){
                conceptualBO = (ConceptualBO)saleBO.getProduct();
                
                storeProductBO = storeProductDAO.read(storeBO.getStoreID(), conceptualBO.getProductID());
                storeProductBO.setQtyOnHand(storeProductBO.getQtyOnHand()+saleBO.getQuantity());
                
                storeProductDAO.save(storeProductBO);
            }//end posting of conceptual sale
            
        }if(saleBO.getReturnLine()==false){
            if(saleBO.getProduct().getProdType().equals("physical")){
                forSaleBO = (ForSaleBO)saleBO.getProduct();
                
                forSaleBO.setSold(true);
                storeProductBO = storeProductDAO.read(storeBO.getStoreID(), forSaleBO.getConceptual().getProductID());
                storeProductBO.setQtyOnHand(storeProductBO.getQtyOnHand()-saleBO.getQuantity());
                
                storeProductDAO.save(storeProductBO);
                forSaleDAO.save(forSaleBO);
            }//end posting of physical sale
            if(saleBO.getProduct().getProdType().equals("conceptual")){
                conceptualBO = (ConceptualBO)saleBO.getProduct();
                
                storeProductBO = storeProductDAO.read(storeBO.getStoreID(), conceptualBO.getProductID());
                storeProductBO.setQtyOnHand(storeProductBO.getQtyOnHand()-saleBO.getQuantity());
                
                storeProductDAO.save(storeProductBO);
            }//end posting of conceptual sale
            
        }//end posting of sale
        
        
    }//end post sale
    /** gets the rental items by category
     *@param category contains the category.
     */
    public ArrayList<ForRentBO> getAvailableItemsByCategory(String category){
        ArrayList<ForRentBO> itemList = null;
        try {
            itemList = ForRentDAO.getInstance().readByAvailableCat(category);
        } catch (ConnectionPoolException ex) {
            ex.printStackTrace();
        } catch (DataException ex) {
            ex.printStackTrace();
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
        return itemList;
    }
    /**
     * 
     * @return 
     */
    public ArrayList<ForRentBO> getAllAvailableRentalItems(){
        ArrayList<ForRentBO> itemList = null;
        try {
            itemList = ForRentDAO.getInstance().readAllForRentObjects();
        } catch (ConnectionPoolException ex) {
            ex.printStackTrace();
        } catch (DataException ex) {
            ex.printStackTrace();
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
        return itemList;
    }
    /**
     * 
     * @return 
     */
    public String[] getAllAvailableRentalProdDescriptions(){
        ArrayList<ForRentBO> forRentList = null;
        ArrayList<String> forRentDescriptionList = new ArrayList<String>();
        String[] forRentDescArray = null;
        String[] forRentNameArray = null;
        try {
            forRentList = ForRentDAO.getInstance().readAllForRentObjects();
        } catch (DataException ex) {
            ex.printStackTrace();
        } catch (ConnectionPoolException ex) {
            ex.printStackTrace();
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
        //convert them to conceptualRentalBO objects
        ArrayList<ConceptualRentalBO> crList = new ArrayList<ConceptualRentalBO>();
        //now parse them for the needed information
        forRentDescArray = new String[forRentList.size()];
        forRentNameArray = new String[forRentList.size()];
        for (int i = 0; i < forRentList.size(); i++) {
            forRentNameArray[i] = forRentList.get(i).getConceptual().getProductName();
            forRentDescArray[i] = forRentList.get(i).getConceptual().getDescription();
        }
        return forRentNameArray;
    }
    /**
     * 
     * @param category 
     * @param keyword 
     * @return 
     */
    public ArrayList<ForRentBO> lookupByKeyword(String category, String keyword){
        ArrayList<ForRentBO> itemList = null;
        try {
            itemList = ForRentDAO.getInstance().lookupByKeyword(category, keyword);
        } catch (ConnectionPoolException ex) {
            ex.printStackTrace();
        } catch (DataException ex) {
            ex.printStackTrace();
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
        return itemList;
    }
    /**
     * 
     * @param frItem 
     * @return 
     */
    public ArrayList<String> populateRentalPanel(ForRentBO frItem) {
        ArrayList<String> fieldList = new ArrayList<String>();
        try {
            
            RentalBO r = (RentalBO)RentalDAO.getInstance().create();
            //get the conceptual product for the rental object selected
            ConceptualRentalBO cr = (ConceptualRentalBO)ConceptualRentalDAO.getInstance().read(frItem.getConceptual().getProductID());
            
            fieldList.add(Double.toString(cr.getPricePerDay()));
            fieldList.add(Double.toString(cr.getReplacementPrice()));
            fieldList.add(Integer.toString(cr.getMaxTimesRented()));
            fieldList.add(Double.toString(cr.getLateFeePerDay()));
            fieldList.add(frItem.getSKU());
            fieldList.add(frItem.getProductID());
            fieldList.add(frItem.getConceptual().getDescription());
            
//            fieldList.add((r.getDateOut()));
//            fieldList.add((r.getDateDue()));
//            fieldList.add((r.getDateIn()));
        } catch (ConnectionPoolException ex) {
            ex.printStackTrace();
        } catch (SQLException ex) {
            ex.printStackTrace();
        } catch (DataException ex) {
            ex.printStackTrace();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return fieldList;
    }
    /**
     * 
     * @param rb 
     * @return 
     */
    public ArrayList<String> populateRentalPanel(RentalBO rb) {
        ArrayList<String> fieldList = new ArrayList<String>();
        try {
            //get the conceptual product for the rental object selected
            ConceptualRentalBO cr = (ConceptualRentalBO)ConceptualRentalDAO.getInstance().read(rb.getProduct().getProductID());
            fieldList.add(rb.getDateOut());
            fieldList.add(rb.getDateDue());
            fieldList.add(Double.toString(cr.getPricePerDay()));
            fieldList.add(Double.toString(cr.getReplacementPrice()));
            fieldList.add(Integer.toString(cr.getMaxTimesRented()));
            fieldList.add(Double.toString(cr.getLateFeePerDay()));
            fieldList.add(rb.getProduct().getSKU());
            fieldList.add(rb.getProduct().getProductID());
            fieldList.add(rb.getDescription());
            
//            fieldList.add((r.getDateOut()));
//            fieldList.add((r.getDateDue()));
//            fieldList.add((r.getDateIn()));
        } catch (ConnectionPoolException ex) {
            ex.printStackTrace();
        } catch (SQLException ex) {
            ex.printStackTrace();
        } catch (DataException ex) {
            ex.printStackTrace();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return fieldList;
    }
    /*********************************************************create method to calculate difference in
     *days and the price based on the price per day
     */
    private double calcPrice(String dateOut, String dateDue, double pricePerDay) {
        return 0;
    }
    /**
     * 
     * @param SKU 
     * @param days 
     * @return 
     */
    public RevenueSourceBO makeRSBO(String SKU, int days) {
        ConceptualRentalBO crbo = null;
        ForRentBO forRentBO = null;
        ArrayList<String> forRentDescriptionList = new ArrayList<String>();
        String[] forRentDescArray = null;
        String[] forRentNameArray = null;
        try {
            forRentBO = (ForRentBO) ForRentDAO.getInstance().readBySKU(SKU);
            crbo = getConcepRentalByPhyProdID(forRentBO.getProductID());
        } catch (ConnectionPoolException ex) {
            ex.printStackTrace();
        } catch (SQLException ex) {
            ex.printStackTrace();
        } catch (DataException ex) {
            ex.printStackTrace();
        }
        
        //set the date for the transaction
        Calendar cal = Calendar.getInstance();
        Date today = cal.getTime();
        SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
        String todaysDate = fmt.format(today);
        RentalBO rbo = null;
        try {
            rbo = (RentalBO) RentalDAO.getInstance().create(forRentBO);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        
        rbo.setDateOut(todaysDate);
        MyDate md = new MyDate();
        md = md.stringToMyDate(todaysDate);
        md.addDay(days);
        String dueDate = md.getFullDateString();
        rbo.setDateDue(dueDate);
        rbo.setDescription("bob");
        NumberFormat currencyFormat = NumberFormat.getCurrencyInstance();

        rbo.setPricePerDay(crbo.getPricePerDay());
        String prodName = crbo.getProductName();
        String prodDescription = crbo.getDescription();
        double pricePerDay = rbo.getPricePerDay();
        
        String doubleWith$and2decimalPlace = currencyFormat.format(pricePerDay);
        
        rbo.setDescription(prodName + ", (" + prodDescription + "), " + days + " day rental @ " + doubleWith$and2decimalPlace + "/day");
        // need to get the price per day from the crbo.
        rbo.setPrice(days * rbo.getPricePerDay());
        RevenueSourceBO revSrcBO = (RevenueSourceBO)rbo;
        revSrcBO.setType("rental");
        try {
            RentalDAO.getInstance().save(revSrcBO);
        } catch (Exception ex) { }
        return revSrcBO;
    }
    /**
     * 
     * @param productID 
     * @return 
     */
    public ConceptualRentalBO getConcepRentalByPhyProdID(String productID) {
        //if ((ProductDAO.getInstance().read(productID).getProdType()=="rental")))
        ForRentBO fbo = null;
        ConceptualRentalBO crbo = null;
        try {
            fbo = (ForRentBO) ForRentDAO.getInstance().read(productID);
            String conceptualRentalID = fbo.getConceptual().getProductID();
            crbo = (ConceptualRentalBO) ConceptualRentalDAO.getInstance().read(conceptualRentalID);
        } catch (SQLException ex) {
            ex.printStackTrace();
        } catch (DataException ex) {
            ex.printStackTrace();
        } catch (ConnectionPoolException ex) {
            ex.printStackTrace();
        }
        return crbo;
    }
    /**
     * 
     * @param rbo 
     * @return 
     */
    public ConceptualRentalBO getConcepRentalByRentalBO(RentalBO rbo) {
        String frboProductID = rbo.getProduct().getProductID();
        ConceptualRentalBO crbo = getConcepRentalByPhyProdID(frboProductID);
        return crbo;
    }
}